
#include <align.h>
#include <as.h>

#include "runtime_types.h"
#include "mem_sys.h"


bool
runtime_sys_create(struct runtime_Mem_Area *area, uintptr prefer_start_page, uintptr pages)
{
	void *prefer_start = (void *)(prefer_start_page * PAGE_SIZE);
	if (prefer_start == NULL) {
		prefer_start = AS_AREA_ANY;
	}

	size_t as_size = pages * PAGE_SIZE;

	// TODO: Record allocation to the memory stats.

	void *p = as_area_create(prefer_start, as_size,
		AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE | AS_AREA_LATE_RESERVE);

	if (p == AS_MAP_FAILED) {
		return false;
	}

	// Closures need executable heap.
	if (as_area_change_flags(p, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_EXEC |
		AS_AREA_CACHEABLE | AS_AREA_LATE_RESERVE) != 0) {

		as_area_destroy(p);
		return false;
	}

	area->area_start = p;
	area->total_pages = pages;
	return true;
}

void
runtime_sys_destroy(struct runtime_Mem_Area *area)
{
	as_area_destroy(area->area_start);
	area->area_start = NULL;
	area->total_pages = 0;
	// TODO: Record memory stats.
}

bool
runtime_sys_resize(struct runtime_Mem_Area *area, uintptr pages)
{
	// TODO: Resize area.
	// TODO: Record memory stats.
	return false;
}

bool
runtime_sys_claim(struct runtime_Mem_Area *area, uintptr start_page, uintptr pages)
{
	// Since we allocate an area with LATE_RESERVE, we don't need to claim any memory
	// manually, but the task will just crash when out of memory. 

	// TODO: Record memory stats.
	// TODO: Claim pages manually.
	return true;
}

void
runtime_sys_release(struct runtime_Mem_Area *area, uintptr start_page, uintptr pages)
{
	// So far there is no syscall for this.

	// TODO: Record memory stats.
	// TODO: Release unused pages.
}

void *
runtime_sys_alloc(uintptr size)
{
	// TODO: Record memory stats.
	size = ALIGN_UP(size, PAGE_SIZE);
	void *m = as_area_create(AS_AREA_ANY, size,
		AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);

	// No user of this function needs executable memory.

	if (m == AS_MAP_FAILED) {
		return NULL;
	}
	return m;
}

void
runtime_sys_free(void *m)
{
	// TODO: Record memory stats.
	as_area_destroy(m);
}
